#include "njm_entity_mgr.hpp"

namespace njm
{
    EntityManager::EntityManager()
    {
        Init();
    }

    EntityManager::~EntityManager()
    {
    }

    void EntityManager::Init()
    {
        for (Entity entity = 0; entity < maxEntities; ++entity)
        {
            availableEntities.push(entity);
        }
        entitySignatures.fill(nullSignature);
        currentLivingEntityCount = 0;
    }

    void EntityManager::Clear()
    {
        Init();
    }

    Entity EntityManager::CreateEntity()
    {
        if (currentLivingEntityCount >= maxEntities)
        {
            throw std::runtime_error("Too many entities in existence.");
        }
        if (availableEntities.empty())
        {
            throw std::runtime_error("No more entities available.");
        }
        Entity entity = availableEntities.front();
        availableEntities.pop();
        ++currentLivingEntityCount;
        return entity;
    }

    void EntityManager::DestroyEntity(Entity entity)
    {
        assert(entity < maxEntities && "Entity out of range.");
        entitySignatures[entity].reset();
        availableEntities.push(entity);
        --currentLivingEntityCount;
    }

    void EntityManager::SetSignature(Entity entity, Signature signature)
    {
        assert(entity < maxEntities && "Entity out of range.");
        entitySignatures[entity] = signature;
    }

    Signature EntityManager::GetSignature(Entity entity)
    {
        assert(entity < maxEntities && "Entity out of range.");
        return entitySignatures[entity];
    }

    bool EntityManager::HasSignature(Entity entity, Signature signature)
    {
        assert(entity < maxEntities && "Entity out of range.");
        return (entitySignatures[entity] & signature) == signature;
    }

    bool EntityManager::HasAnySignature(Entity entity, Signature signature)
    {
        assert(entity < maxEntities && "Entity out of range.");
        // return (entitySignatures[entity] & signature) != 0;
        return (entitySignatures[entity] & signature).any();
    }

    std::vector<Entity> EntityManager::GetEntitiesWithSignature(Signature signature)
    {
        std::vector<Entity> entities;
        for (Entity entity = 0; entity < maxEntities; ++entity)
        {
            if (HasSignature(entity, signature))
            {
                entities.push_back(entity);
            }
        }
        return entities;
    }
}